from threading import Thread
from time import sleep
#import hashlib
import socket
import sys
import re
import os

# 保证读取文件时较少的内存占用
def read_inPieces(read_inPieces_file, read_inPieces_size=131072):
    while True:
        read_inPieces_piece = read_inPieces_file.read(read_inPieces_size)
        if not read_inPieces_piece:
            break
        yield read_inPieces_piece

# 取得本地IP地址
s_ip_i = 0
while s_ip_i<3:
    try:
        s_ip_i += 1
        s_ip = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s_ip.connect(("223.5.5.5",53))
        print('Cast ip : ', s_ip.getsockname()[0])
        s_ip.close()
        break
    except:
        s_ip_i += 1

# 保证在传输结束后，端口可复用
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
port = 1079
s.bind(('', port))

file=input('Cast file path : ')
file=file.strip('\"\'\\/')

# 声明压缩目录的多线程函数
def dir2zip():
    import shutil
    global file, if_dir2zip_done
    shutil.make_archive(file, 'zip', file)
    file = file+'.zip'
    if_dir2zip_done = True

# if_dir2zip_done用于等待dir2zip多线程函数的完成
# if_remove_dir2zip用于声明是否是目录+是否在完成传输后删除临时文件zip
if_remove_dir2zip = False
if os.path.exists(file)==False:
    print('? : Not Found : '+file)
    sys.exit(0)
elif os.path.isdir(file):
    if_remove_dir2zip = True
    if_dir2zip_done = False
    try:
        os.remove(file+'.zip')
    except:pass
    t=Thread(target=dir2zip)
    t.start()
else:
    if_dir2zip_done = True

print("? : Connection", end='\r')
#print(hashlib.md5(open(file, "rb").read()).hexdigest())

s.listen(10)
c, addr = s.accept()
print('{} connected.'.format(addr))

while if_dir2zip_done==False:
    # 如果不加sleep，那么while-pass导致的io阻塞会很严重
    sleep(0.5)
    pass

print('Cast ... ( ', file, ' )')
# 对接收者告知是否是目录
if if_remove_dir2zip == True:
    if_remove_dir2zip_signal = b'0x01'
else:
    if_remove_dir2zip_signal = b'0x02'
c.send(os.path.basename(file).encode('utf-8')+b'0x00'+if_remove_dir2zip_signal+b'0x00'+str(os.path.getsize(file)).encode('utf-8')+b'0x00')
with open(file, "rb") as open_file:
    for piece in read_inPieces(open_file):
        c.sendall(piece)
s.close()

print("Cast : Done")

if if_remove_dir2zip == True:
    os.remove(file)
